package com.tbit.uqbike.service.business.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tbit.common.config.OssDefaultConfig;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.Account;
import com.tbit.uqbike.object.pojo.OssConfig;
import com.tbit.uqbike.object.pojo.Voice;
import com.tbit.uqbike.object.pojo.VoiceTask;
import com.tbit.uqbike.object.pojo.dto.VoiceDTO;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.service.business.VoiceService;
import com.tbit.uqbike.webmanager.controller.BaseController;
import com.tbit.uqbike.webmanager.dao.core.AccountDao;
import com.tbit.uqbike.webmanager.dao.core.OssConfigDao;
import com.tbit.uqbike.webmanager.dao.core.VoiceDao;
import com.tbit.uqbike.webmanager.dao.core.VoiceTaskDao;
import com.tbit.uqbike.webmanager.util.ServletUtils;
import com.tbit.uqbike.webmanager.util.aliyun.OssFileUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;

/**
 * 自定义语音Service
 *
 * @author <a href="mailto:liu.haoxiang@tbit.com.cn">BUGXiang</a>
 * @version 1.0
 * @since 2024/3/14
 */
@Service
@Slf4j
public class VoiceServiceImpl extends ServiceImpl<VoiceDao, Voice> implements VoiceService {

    @Resource
    private VoiceDao voiceDao;
    @Resource
    private OssConfigDao ossConfigDao;
    @Resource
    private VoiceTaskDao voiceTaskDao;
    @Resource
    private OssDefaultConfig ossDefaultConfig;
    @Resource
    private VoiceTaskServiceImpl voiceTaskService;


    /**
     * 分页查询语音列表
     *
     * @param voiceDTO voiceDTO
     * @return Result<PageInfo < Voice>>
     */
    @Override
    public Result<PageResult<Voice>> queryPage(VoiceDTO voiceDTO) {
        if (Objects.nonNull(voiceDTO.getPageNumber()) && Objects.nonNull(voiceDTO.getSize())) {
            PageInfo<Voice> pageInfo = PageHelper.startPage(voiceDTO.getPageNumber(), voiceDTO.getSize()).doSelectPageInfo(() -> voiceDao.queryPage(voiceDTO));
            return Result.success(new PageResult<Voice>(voiceDTO.getPageNumber(), voiceDTO.getSize(), pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList()));
        } else {
            return Result.success(new PageResult<>(null, null, null, null, voiceDao.queryPage(voiceDTO)));
        }
    }

    /**
     * 新增语音
     *
     * @param brandId   品牌id
     * @param accountId 区域id
     * @param voiceName 语音名称
     * @param delFlag   上架状态(0=上架 1=下架)
     * @param file      语音文件
     * @return result
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> add(Integer brandId, Integer accountId, String voiceName, Integer delFlag, MultipartFile file, LoginInfo login) {
        QueryWrapper<Voice> voiceQueryWrapper = new QueryWrapper<>();
        voiceQueryWrapper.eq("voiceName", voiceName);
        Voice voice = voiceDao.selectOne(voiceQueryWrapper);
        if (voice != null && voice.getVoiceId() != null) {
            return Result.error("语音文件名称重复，请重新输入");
        }
        String fileUrl = uploadAliYunOss(brandId, file);
        //维护语音id
        Map<Integer, Object> voiceIdMap = voiceDao.selectVoiceId(accountId);
        voice = new Voice();
        voice.setVoiceName(voiceName)
                .setVoiceId(createVoiceId(voiceIdMap))
                .setAccountId(accountId)
                .setDelFlag(delFlag)
                .setFileUrl(fileUrl)
                .setFileName(file.getOriginalFilename())
                .setCreateUser(login.getId().toString())
                .setCreateTime(new Date());

        voiceDao.insert(voice);
        return Result.success();
    }

    /**
     * 修改语音
     *
     * @param id        语音id
     * @param brandId   品牌id
     * @param accountId 区域id
     * @param voiceName 语音名称
     * @param delFlag   上架状态(0=上架 1=下架)
     * @param file      语音文件
     * @return result
     */
    @Override
    public Result<Object> update(Integer id, Integer brandId, Integer voiceId, Integer accountId, String voiceName, Integer delFlag, MultipartFile file) {
        QueryWrapper<Voice> voiceQueryWrapper = new QueryWrapper<>();
        voiceQueryWrapper.eq("voiceName", voiceName).ne("id", id);
        Voice voice = voiceDao.selectOne(voiceQueryWrapper);
        if (voice != null && voice.getVoiceId() != null) {
            return Result.error("语音文件名称重复，请重新输入");
        }
        //校验是否被使用
        if (1 == delFlag) {
            QueryWrapper<VoiceTask> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id", id);
            List<VoiceTask> voiceTasks = voiceTaskDao.selectList(queryWrapper);
            if (voiceTasks.size() > 0) {
                return Result.error("不可下架！请取消语音任务，再进行语音下架处理");
            }
        }
        String fileUrl = null;
        if (Objects.nonNull(file)) {
            fileUrl = uploadAliYunOss(brandId, file);
        }
        voice = new Voice();
        voice.setId(id)
                .setVoiceName(voiceName)
                .setAccountId(accountId)
                .setDelFlag(delFlag)
                .setFileUrl(fileUrl)
                .setFileName(file == null ? null : file.getOriginalFilename())
                .setUpdateTime(new Date());
        voiceDao.updateVoiveById(voice);
        //10分钟后升级
        voiceTaskService.timer(brandId, accountId, BaseController.getLogin(ServletUtils.getRequest()));
        return Result.success();
    }

    /**
     * 删除语音
     *
     * @param id id
     */
    @Override
    public Result<Object> deleteId(Integer id) {
        QueryWrapper<VoiceTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        List<VoiceTask> voiceTasks = voiceTaskDao.selectList(queryWrapper);
        if (voiceTasks.size() > 0) {
            return Result.error("不可删除！请取消语音任务，再进行删除处理！");
        }
        voiceDao.deleteById(id);
        return Result.success();
    }


    /**
     * 上传MP3语音文件到阿里云
     *
     * @param brandId 品牌id
     * @param file    MP3文件
     * @return fileUrl
     */
    private String uploadAliYunOss(Integer brandId, MultipartFile file) {
        //语音文件上传到阿里云
        OssConfig ossConfig = Optional.ofNullable(ossConfigDao.getByAccountId(brandId))
                .orElseGet(() -> new OssConfig(ossDefaultConfig.getEndpoint(),
                        ossDefaultConfig.getAccessKeyId(),
                        ossDefaultConfig.getAccessKeySecret(), "gx-voice"));
        //No suitable ImageReader found for source data.
        //阿里云oss上传语音文件失败
        String fileUrl = null;
        try {
            String fileName = String.format("%s/%s%s", brandId, UUID.randomUUID(), file.getOriginalFilename());
            fileUrl = OssFileUtils.uploadByAliYun(file.getInputStream(), ossConfig, fileName, "MP3", 1);
        } catch (Exception e) {
            log.info("上传语音文件到阿里云失败");
            log.error(e.getMessage(), e);
        }
        if (StringUtils.isBlank(fileUrl)) {
            throw new BaseException("上传语音文件失败");
        }
        return fileUrl;
    }


    /**
     * 创建语音id
     *
     * @param voiceIdMap 已存在的语音id
     * @return voiceId
     */
    public Integer createVoiceId(Map<Integer, Object> voiceIdMap) {
        // 生成 1000 到 2000 的连续 ID 数据集，排除入参
        for (int i = 1000; i <= 2000; i++) {
            if (!voiceIdMap.containsKey(i)) {
                return i;
            }
        }
        throw new BaseException("语音id已被分配完，请先删除语音");
    }
}
